#define _CRT_SECURE_NO_WARNINGS

#include "string.h"


using namespace little_monster;

void::string::swap(string& s)
{
	std::swap(_str, s._str);
	std::swap(_capacity, s._capacity);
	std::swap(_size, s._size);
}

string::string(const char* str = "")
	:_size((size_t)strlen(str))
	, _capacity(_size)
{
	_str = new char[_capacity + 1];
	strcpy(_str, str);
}

string::string(const string& s)
	:_str(nullptr)
	,_size(0)
	,_capacity(0)
{
	string tmp(s._str);
	swap(tmp);
}

string::~string()
{
	if(_str)
	{
		delete[] _str;
		_str = nullptr;
		_size = _capacity = 0;
	}
}

size_t string::size() const
{
	return _size;
}

size_t string::capacity() const
{
	return _capacity;
}

bool string::empty()
{
	if (_size == 0)
	{
		return true;
	}
	return false;
}

void string::reserve(size_t n)
{
	if (n > _capacity)
	{
		char* tmp = new char[n + 1];
		strcpy(tmp, _str);
		delete[] _str;
		_str = tmp;
		_capacity = n;
	}
}

void string::clear()
{
	_str[0] = '\0';
	_size = 0;
}

void string::resize(size_t n,char ch = '\0')
{
	if (n <= _size)
	{
		_str[n] = '\0';
	}
	else
	{
		reserve(n);
		while (n > _size)
		{
			_str[_size] = ch;
			++_size;
		}
		_str[_size] = '\0';
	}

}

char& string::operator[](size_t pos)
{
	assert(pos < _size);
	return _str[pos];
}

const char& string::operator[](size_t pos) const
{
	assert(pos < _size);
	return _str[pos];
}

iterator string::begin()
{
	return _str;
}

const_iterator string::begin() const
{
	return _str;
}

iterator string::end()
{
	return _str + _size;
}

const_iterator string::end() const
{
	return _str + _size;
}

void string::push_back(char ch)
{
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : 2 * _capacity);
	}
	_str[_size++] = ch;
	_str[_size] = '\0';
}

void string::append(const char* str)
{
	size_t len = strlen(str);
	if (_capacity < (len + _size))
	{
		reserve(len + _size);
	}
	strcpy(_str + _size, str);
	_size += len;
}

string& string::operator+=(char ch)
{
	push_back(ch);
	return *this;
}

string& string::operator+=(const char* str)
{
	append(str);
	return *this;
}

void string::insert(size_t pos, char ch)
{
	assert(pos <= _size);
	size_t n = _size + 1;
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : 2 * _capacity);
	}
	while (pos < n)
	{
		_str[n] = _str[n - 1];
		--n;
	}
	_str[pos] = ch;
	++_size;
}

void string::insert(size_t pos, const char* str)
{
	assert(pos <= _size);
	size_t len = strlen(str);
	if (len + _size > _capacity)
	{
		reserve(len + _size);
	}
	int n = (int)_size;
	while (n >= (int)pos)
	{
		_str[n + len] = _str[n];
		--n;
	}
	strncpy(_str + pos, str, len);
	_size += len;
}

void string::erase(size_t pos, size_t len = npos)
{
	assert(pos < _size);
	if (len == npos || len + pos > _size)
	{
		_str[pos] = '\0';
		_size = pos;
	}
	else
	{
		size_t begin = pos + len;
		while (begin < _size)
		{
			_str[begin - len] = _str[begin];
			begin++;
		}
		_size -= len;
	}
}

size_t string::find(char ch, size_t pos = 0)
{
	for (int i = (int)pos; i < _size; i++)
	{
		if (_str[i] == ch)
		{
			return i;
		}
	}
	return npos;
}

size_t string::find(const char* sub, size_t pos = 0)
{
	const char* p = strstr(_str, sub);
	if (p)
	{
		return p - _str;
	}
	return npos;
}

string string::substr(size_t pos, size_t len = npos)
{
	string s;
	size_t end = pos + len;
	if (len == npos || pos + len >= _size)
	{
		len = _size - pos;
		end = _size;
	}

	s.reserve(len);
	for (size_t i = pos; i < end; i++)
	{
		s += _str[i];
	}

	return s;
}

string& string::operator=(string tmp)
{
	swap(tmp);

	return *this;
}

const char* string::c_str() const
{
	return _str;
}

bool string::operator<(const string& s) const
{
	return strcmp(_str, s._str) < 0;
}

bool string::operator==(const string& s) const
{
	return strcmp(_str, s._str) == 0;
}

bool string::operator>(const string& s) const
{
	return !(*this < s) || !(*this == s);
}
bool string::operator<=(const string& s) const
{
	return !(*this > s);
}
bool string::operator>=(const string& s) const
{
	return !(*this < s);
}
bool string::operator!=(const string& s) const
{
	return !(*this == s);
}


